﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
using System.Text;

/// <summary>
/// Summary description for Archivo
/// </summary>
public class Archivo
{
    private const int ARCHIVO_ENTRADA_ALMACEN = 1;
    private const int ARCHIVO_SALIDA_ALMACEN = 2;
    private const int ARCHIVO_INVENTARIO = 3;
    private const string MOVIMIENTO = "Movimiento";
    private const string DOCUMENTO = "Documento";
    private const string NUMERICO = "Numérico";
    private const string ALFANUMERICO = "Alfanumérico";
    private const string DECIMAL = "Decimal";

    /// <summary>
    /// Delcaraciones de Conexion a la BD
    /// </summary>
    #region Conexion
    private string strCEDIS = ConfigurationManager.ConnectionStrings["CEDIS"].ToString();
    #endregion

	public Archivo()
	{
	}

    /// <summary>
    /// Retorna listado de archivos existentes
    /// </summary>
    /// <returns></returns>
    public DataSet GetArchivos()
    {
        DataSet dts = SqlHelper.ExecuteDataset(strCEDIS, CommandType.StoredProcedure, "GetArchivos");        
        return dts;
    }

    /// <summary>
    /// Retorna información del archivo que le llega e info de los items del archivo
    /// </summary>
    /// <returns></returns>
    public DataSet GetArchivo(int idArchivo)
    {
        SqlParameter[] param = new SqlParameter[1];
        param[0] = new SqlParameter("@IdArchivo", idArchivo);

        DataSet dts = SqlHelper.ExecuteDataset(strCEDIS, CommandType.StoredProcedure, "GetArchivo", param);
        return dts;
    }

    /// <summary>
    /// Actualiza el valor de un item de archivo
    /// </summary>
    /// <param name="idArchivo"></param>
    /// <param name="valor"></param>
    public void ActualizarArchivoItem(int idArchivoItem, string valor)
    {
        SqlParameter[] param = new SqlParameter[2];
        param[0] = new SqlParameter("@Id", idArchivoItem);
        param[1] = new SqlParameter("@Valor", valor);

        SqlHelper.ExecuteNonQuery(strCEDIS, CommandType.StoredProcedure, "ActualizarArchivoItem", param);        
    }

    /// <summary>
    /// Valida que el valor que le llega cumple con el tipo y longitud definidos
    /// </summary>
    /// <param name="valor"></param>
    /// <param name="tipo"></param>
    /// <param name="longitud"></param>
    /// <returns></returns>
    public string ValidarItem(string valor, string tipo, int longitud)
    {
        string resultado = "";

        if (valor.Trim().Length == 0)
            resultado = "El valor no puede quedar vacío";
        else if (valor.Length > longitud)
            resultado = "La longitud de este ítem no puede ser mayor a " + longitud.ToString();

        if (resultado.Length == 0)
        {
            //Si solo se permiten numeros
            if (tipo == "Numérico")
            {
                string expresion = @"^[0-9]+$";
                if ((!Regex.IsMatch(valor, expresion)) && (valor.Length > 0))
                    resultado = "Solo puede contener números";
            }
        }

        return resultado;
    }

    #region "Entrada almacen"


    public void GenerarArchivoEntradaAlmacen(string ruta, DataTable dtCodigosBarra, string codigoTercero, string sucursalProveedor, string terceroComprador, string consecutivoDocumento)
    {
        ruta = Path.Combine(ruta, "Entrada" + DateTime.Now.ToString("yyyyMMdd-hhmmss") + ".txt");

        // Se crea al archivo
        StreamWriter sw = new StreamWriter(ruta);
        try 
	    {	        
            sw.WriteLine(ArchivoHelper.cadenaInicio());
            sw.WriteLine(DocumentoVersion03(codigoTercero, sucursalProveedor, terceroComprador, consecutivoDocumento));

            int contadorFilas = 3;
            if (dtCodigosBarra.Rows.Count > 0)
            {                
                for (int i = 0; i < dtCodigosBarra.Rows.Count; i++)
                {
                    sw.WriteLine(this.MovimientoVersion02(contadorFilas, dtCodigosBarra.Rows[i]["codbodega"].ToString(), dtCodigosBarra.Rows[i]["codunidadmedida"].ToString(), dtCodigosBarra.Rows[i]["fechaentrega"].ToString(), dtCodigosBarra.Rows[i]["cantidad"].ToString(), dtCodigosBarra.Rows[i]["codigobarra"].ToString()));
                    contadorFilas += 1;                      
                }
            }

            //Se crea la fila que cierra el archivo. NOTA: Se utiliza write (no WriteLine) para que no agregue un salto de linea final
            sw.Write(ArchivoHelper.cadenaFinal(contadorFilas));
	    }
	    catch (Exception ex)
	    {
		    throw new Exception("Error al crear el archivo: " + ex.Message);		
	    }
        finally
        {
            sw.Close();
        }
    }

    /// <summary>
    /// Construye la linea del encabezado del archivo correspondiente a dcto de entrada de almacen Documento versión 03
    /// </summary>    
    /// <returns></returns>
    private string DocumentoVersion03(string codigoTercero, string sucursalProveedor, string terceroComprador, string consecutivoDocumento)
    {
        //Obtiene la infomración de la base de datos
        DataSet dts = this.GetArchivo(ARCHIVO_ENTRADA_ALMACEN);                
        DataTable dt = dts.Tables[1].DefaultView.ToTable();

        StringBuilder registro = new StringBuilder();
        string tipoDato = "";
        int longitud = 0;
        string valor = "";
        int orden = 0;
        int digitosEnteros = 0;
        for (int i = 0; i<dt.Rows.Count; i++)
        {
            tipoDato = dt.Rows[i]["tipo"].ToString();
            longitud = Convert.ToInt32(dt.Rows[i]["longitud"].ToString());
            orden = Convert.ToInt32(dt.Rows[i]["orden"].ToString());
            digitosEnteros = Convert.ToInt32(dt.Rows[i]["digitosEnteros"].ToString());
            valor = "";
            
            //Si la columna es calculada 
            if (Convert.ToInt32(dt.Rows[i]["calculada"].ToString()) == 1)                        
            {
                //Se determina qué columna es (por el numero de orden) para poner el valor correspondiente
                switch(orden)
                {
                    case 11:        //Fecha del documento
                        valor = DateTime.Today.ToString("yyyyMMdd");
                        break;
                    case 12:        //Codigo del tercero
                        valor = codigoTercero;
                        break;
                    case 19:        //Sucursal del proveedor
                        valor = sucursalProveedor;
                        break;
                    case 20:        //Tercero comprador
                        valor = terceroComprador;
                        break;
                    case 43:        //Consecutivo documento OC
                        valor = consecutivoDocumento;
                        break;
                    default:
                        throw new Exception("No se encontró el dato para construir el documento version 03 (orden " + orden.ToString() + "). Verifique en la tabla ARCHIVO_ITEM la columna calculada");
                }                
            }
            else
            {
                if (dt.Rows[i]["valor"] != DBNull.Value)
                    valor = dt.Rows[i]["valor"].ToString().Trim();
            }

            if (tipoDato == NUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", longitud);
            else if (tipoDato == ALFANUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, " ", longitud);
            else if (tipoDato == DECIMAL)
            {
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", digitosEnteros) + ".";
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, "0", longitud);                
            }
            
            registro.Append(valor);
        }

        return registro.ToString();
    }


    private string MovimientoVersion02(int contadorFilas, string codigoBodega, string unidadMedida, string fechaEntrega, string cantidadBase, string codigoBarras)
    {
        //Obtiene la infomración de la base de datos
        DataSet dts = this.GetArchivo(ARCHIVO_ENTRADA_ALMACEN);
        DataTable dt = dts.Tables[2].DefaultView.ToTable();

        StringBuilder registro = new StringBuilder();
        string tipoDato = "";
        int longitud = 0;
        string valor = "";
        int orden = 0;
        int digitosEnteros = 0;
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            tipoDato = dt.Rows[i]["tipo"].ToString();
            longitud = Convert.ToInt32(dt.Rows[i]["longitud"].ToString());
            orden = Convert.ToInt32(dt.Rows[i]["orden"].ToString());
            digitosEnteros = Convert.ToInt32(dt.Rows[i]["digitosEnteros"].ToString());
            valor = "";

            //Si la columna es calculada 
            if (Convert.ToInt32(dt.Rows[i]["calculada"].ToString()) == 1)
            {
                switch (orden)
                {
                    case 1:        //Contador de filas
                        valor = contadorFilas.ToString();
                        break;
                    case 12:        //Código de barras
                        valor = codigoBarras;
                        break;
                    case 15:        //Código de bodega
                        valor = codigoBodega;
                        break;
                    case 18:        //Unidad de medida
                        valor = unidadMedida;
                        break;
                    case 19:        //Fecha de entrega
                        valor = fechaEntrega;
                        break;
                    case 20:        //Cantidad base
                        valor = cantidadBase;
                        break;                    
                    default:
                        throw new Exception("No se encontró el dato para construir el movimiento version 02 (orden " + orden.ToString() + "). Verifique en la tabla ARCHIVO_ITEM la columna calculada");
                }
            }
            else
            {
                if (dt.Rows[i]["valor"] != DBNull.Value)
                    valor = dt.Rows[i]["valor"].ToString().Trim();
            }

            if (tipoDato == NUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", longitud);
            else if (tipoDato == ALFANUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, " ", longitud);
            else if (tipoDato == DECIMAL)
            {
                //Si es de tipo decimal se toma la parte entera y la parte decimal
                string parteEntera = valor;
                string parteDecimal = "";
                if (valor.Contains("."))
                {
                    parteEntera = valor.Substring(0, valor.IndexOf("."));
                    parteDecimal = valor.Substring(valor.IndexOf(".") + 1);
                }

                if (valor.Contains(","))
                {
                    parteEntera = valor.Substring(0, valor.IndexOf(","));
                    parteDecimal = valor.Substring(valor.IndexOf(",") + 1);
                }

                parteEntera = ArchivoHelper.CompletarCadenaAlInicio(parteEntera, "0", digitosEnteros);
                valor = parteEntera + "." + parteDecimal;
                                
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, "0", longitud);                
            }

            registro.Append(valor);
        }

        return registro.ToString();
        
    }

#endregion


    #region "Inventarios"

    public void GenerarArchivoInventarios(string ruta, DataTable dtCodigosBarra)
    {
        ruta = Path.Combine(ruta, "Inventario" + DateTime.Now.ToString("yyyyMMdd-hhmmss") + ".txt");

        // Se crea al archivo
        StreamWriter sw = new StreamWriter(ruta);
        try
        {
            sw.WriteLine(ArchivoHelper.cadenaInicio());
            sw.WriteLine(DocumentoInventarioVersion02());

            int contadorFilas = 3;            
            if (dtCodigosBarra.Rows.Count > 0)
            {
                for (int i = 0; i < dtCodigosBarra.Rows.Count; i++)
                {
                    if (dtCodigosBarra.Rows[i]["EAN13"].ToString().Trim().Length > 0)
                        sw.WriteLine(this.MovimientoInventarioVersion03(contadorFilas, "1", dtCodigosBarra.Rows[i]["EAN13"].ToString(), i + 1));                    
                    else
                        sw.WriteLine(this.MovimientoInventarioVersion03(contadorFilas, "1", dtCodigosBarra.Rows[i]["EAN14"].ToString(), i + 1));                    
                    contadorFilas += 1;
                }
            }

            //Se crea la fila que cierra el archivo. NOTA: Se utiliza write (no WriteLine) para que no agregue un salto de linea final
            sw.Write(ArchivoHelper.cadenaFinal(contadorFilas));
        }
        catch (Exception ex)
        {
            throw new Exception("Error al crear el archivo: " + ex.Message);
        }
        finally
        {
            sw.Close();
        }
    }

    /// <summary>
    /// Construye la linea del encabezado del archivo correspondiente a dcto de inventarios Documento versión 03
    /// </summary>    
    /// <returns></returns>
    private string DocumentoInventarioVersion02()
    {
        //Obtiene la infomración de la base de datos
        DataSet dts = this.GetArchivo(ARCHIVO_INVENTARIO);
        DataTable dt = dts.Tables[1].DefaultView.ToTable();

        StringBuilder registro = new StringBuilder();
        string tipoDato = "";
        int longitud = 0;
        string valor = "";
        int orden = 0;
        int digitosEnteros = 0;
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            tipoDato = dt.Rows[i]["tipo"].ToString();
            longitud = Convert.ToInt32(dt.Rows[i]["longitud"].ToString());
            orden = Convert.ToInt32(dt.Rows[i]["orden"].ToString());
            digitosEnteros = Convert.ToInt32(dt.Rows[i]["digitosEnteros"].ToString());
            valor = "";

            //Si la columna es calculada 
            if (Convert.ToInt32(dt.Rows[i]["calculada"].ToString()) == 1)
            {
                //Se determina qué columna es (por el numero de orden) para poner el valor correspondiente
                switch (orden)
                {
                    case 10:        //Fecha del documento
                        valor = DateTime.Today.ToString("yyyyMMdd");
                        break;
                    default:
                        throw new Exception("No se encontró el dato para construir el documento version 02 (orden " + orden.ToString() + "). Verifique en la tabla ARCHIVO_ITEM la columna calculada");
                }
            }
            else
            {
                if (dt.Rows[i]["valor"] != DBNull.Value)
                    valor = dt.Rows[i]["valor"].ToString().Trim();
            }

            if (tipoDato == NUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", longitud);
            else if (tipoDato == ALFANUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, " ", longitud);
            else if (tipoDato == DECIMAL)
            {
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", digitosEnteros) + ".";
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, "0", longitud);
            }

            registro.Append(valor);
        }

        return registro.ToString();
    }

    private string MovimientoInventarioVersion03(int contadorFilas, string cantidadBase, string codigoBarras, int numeroRegistro)
    {
        //Obtiene la infomración de la base de datos
        DataSet dts = this.GetArchivo(ARCHIVO_INVENTARIO);
        DataTable dt = dts.Tables[2].DefaultView.ToTable();

        StringBuilder registro = new StringBuilder();
        string tipoDato = "";
        int longitud = 0;
        string valor = "";
        int orden = 0;
        int digitosEnteros = 0;        
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            tipoDato = dt.Rows[i]["tipo"].ToString();
            longitud = Convert.ToInt32(dt.Rows[i]["longitud"].ToString());
            orden = Convert.ToInt32(dt.Rows[i]["orden"].ToString());
            digitosEnteros = Convert.ToInt32(dt.Rows[i]["digitosEnteros"].ToString());
            valor = "";

            //Si la columna es calculada 
            if (Convert.ToInt32(dt.Rows[i]["calculada"].ToString()) == 1)
            {
                switch (orden)
                {
                    case 1:        //Contador de filas
                        valor = contadorFilas.ToString();
                        break;
                    case 9:        //Numero de registro
                        valor = numeroRegistro.ToString();
                        break;
                    case 10:        //espacios, Se arregla para poner aqui el codigo de barras
                        valor = "0000000                    " + ArchivoHelper.CompletarCadenaAlFinal(codigoBarras, " ", 20) + "        ";
                        break;
                    case 21:        //Cantidad base
                        valor = cantidadBase;
                        break;
                    case 32:        //Código de barras
                        valor = codigoBarras;
                        break;

                    default:
                        throw new Exception("No se encontró el dato para construir el movimiento version 03 (orden " + orden.ToString() + "). Verifique en la tabla ARCHIVO_ITEM la columna calculada");
                }
            }
            else
            {
                if (dt.Rows[i]["valor"] != DBNull.Value)
                    valor = dt.Rows[i]["valor"].ToString().Trim();
            }

            if (tipoDato == NUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlInicio(valor, "0", longitud);
            else if (tipoDato == ALFANUMERICO)
                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, " ", longitud);
            else if (tipoDato == DECIMAL)
            {
                //Si es de tipo decimal se toma la parte entera y la parte decimal
                string parteEntera = valor;
                string parteDecimal = "";
                if (valor.Contains("."))
                {
                    parteEntera = valor.Substring(0, valor.IndexOf("."));
                    parteDecimal = valor.Substring(valor.IndexOf(".") + 1);
                }

                if (valor.Contains(","))
                {
                    parteEntera = valor.Substring(0, valor.IndexOf(","));
                    parteDecimal = valor.Substring(valor.IndexOf(",") + 1);
                }

                parteEntera = ArchivoHelper.CompletarCadenaAlInicio(parteEntera, "0", digitosEnteros);
                valor = parteEntera + "." + parteDecimal;

                valor = ArchivoHelper.CompletarCadenaAlFinal(valor, "0", longitud);
            }

            registro.Append(valor);
        }

        return registro.ToString();

    }

    #endregion

    #region "Compromisos"

    public void GenerarArchivoCompromiso(string ruta)
    {
        ruta = Path.Combine(ruta, "Compromiso" + DateTime.Now.ToString("yyyyMMdd-hhmmss") + ".txt");

        // Se crea al archivo
        StreamWriter sw = new StreamWriter(ruta);
        try
        {            
            sw.WriteLine(ArchivoHelper.cadenaInicio());

            //string[] arrItems = { "0000024", "0000028", "0000029", "0000030", "0000031", "0000032", "0000033" };
            string[] arrItems = { "7591057001056", "7702103038050", "7591057025229", "7591057001070", "7702103015020", "7501000177196", "7501000177165" };

            //Recorre el arreglo de ítems
            int contadorFilas = 2;
            for (int i = 0; i < arrItems.Length; i++)
            {
                StringBuilder registro = new StringBuilder();
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio(contadorFilas.ToString(), "0", 7));
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("405", "0", 4));
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("00", "0", 2));
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("03", "0", 2));
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("001", "0", 3));  //Compañia
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal("001", " ", 3));  //Centro de operacion
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal("PV", " ", 3));  //Tipo de documento
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("1", "0", 8));  //Consecutivo de documento
                registro.Append(ArchivoHelper.CompletarCadenaAlInicio("0", "0", 7));  //Item
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(" ", " ", 50));  //Referencia
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(arrItems[i], " ", 20));  //Codigo barras
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(" ", " ", 20));  //Extension 1
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(" ", " ", 20));  //Extension 2
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal("ALI1", " ", 5));  //Bodega
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(" ", " ", 10));  //Ubicacion
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal(" ", " ", 15));  //Lote
                registro.Append(ArchivoHelper.CompletarCadenaAlFinal("UND", " ", 4));  //Unidad medida
                registro.Append("000000000000001.0000"); //Cantidad base
                registro.Append("000000000000000.0000"); //Cantidad adicional                

                sw.WriteLine(registro.ToString());                
                contadorFilas += 1;
            }
            

            //Se crea la fila que cierra el archivo. NOTA: Se utiliza write (no WriteLine) para que no agregue un salto de linea final
            sw.Write(ArchivoHelper.cadenaFinal(contadorFilas));
        }
        catch (Exception ex)
        {
            throw new Exception("Error al crear el archivo de compromiso: " + ex.Message);
        }
        finally
        {
            sw.Close();
        }
    }

    #endregion

}